﻿using OpenCvSharp;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace FaceDotnet
{
    /// <summary>
    /// 表示人脸特征
    /// </summary>
    [DebuggerDisplay("{mat}")]
    public class FaceFeature : IDisposable
    {
        private readonly Mat mat;

        /// <summary>
        /// 人脸特征
        /// </summary>
        /// <param name="base64String">base64特征</param>
        public FaceFeature(string base64String)
            : this(Convert.FromBase64String(base64String))
        {
        }

        /// <summary>
        /// 人脸特征
        /// </summary>
        /// <param name="feature">特征码</param>
        public FaceFeature(byte[] feature)
            : this(new Mat(1, feature.Length / sizeof(float), MatType.CV_32FC1, feature))
        {
        }

        /// <summary>
        /// 人脸特征
        /// </summary>
        /// <param name="feature">特征</param>
        internal FaceFeature(Mat feature)
        {
            this.mat = feature;
        }

        /// <summary>
        /// 人脸特征比较
        /// 返回相似度
        /// </summary>
        /// <param name="other">另个一个特征</param>
        /// <returns></returns>
        public double Match(FaceFeature other)
        {
            return other == default ? 0d : this.mat.Dot(other.mat);
        }


        /// <summary>
        /// 将人脸特征转换为byte数组
        /// </summary>
        /// <returns></returns>
        public byte[] ToByteArray()
        {
            this.mat.GetArray<float>(out var data);
            return MemoryMarshal.Cast<float, byte>(data).ToArray();
        }

        /// <summary>
        /// 将人脸特征转换为base64
        /// </summary>
        /// <returns></returns>
        public string ToBase64String()
        {
            var bytes = this.ToByteArray();
            return Convert.ToBase64String(bytes);
        }

        /// <summary>
        /// 将人脸特征转换为base64
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.ToBase64String();
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public virtual void Dispose()
        {
            this.mat.Dispose();
        }
    }
}
